home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / tar_aids < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  8.4 KB

  1. Subject:  v07i002:  Tools to read damaged tar tapes (tar_aids)
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: pyramid!utzoo!henry
  6. Mod.sources: Volume 7, Issue 2
  7. Archive-name: tar_aids
  8.  
  9.  
  10. [  I wrote the Makefile and repacked the archive.  These tools are
  11.    very useful!  --r$  ]
  12.  
  13. #!/bin/sh
  14. # This is a shell archive.  Remove anything before this line,
  15. # then unpack it by saving it in a file and typing "sh file".
  16.  
  17. # Exit status; set to 1 on "wc" errors or if would overwrite.
  18. STATUS=0
  19. # Contents:  README Makefile targ.1 targ.c tarl.c
  20.  
  21. echo x - README
  22. if test -f README ; then
  23.     echo README exists, putting output in $$README
  24.     OUT=$$README
  25.     STATUS=1
  26. else
  27.     OUT=README
  28. fi
  29. sed 's/^XX//' > $OUT <<'@//E*O*F README//'
  30. XXHere are two small public-domain programs for scavenging files from
  31. XXdamaged tar tapes.  They don't sing or dance, but they are highly
  32. XXportable, and they are simple enough that they are readily understood
  33. XXand changed to meet special requirements.  They aren't the most
  34. XXbeautiful code on Earth, since they are basically cleaned-up versions
  35. XXof quick-and-dirty improvisations.  They do, however, work.
  36. @//E*O*F README//
  37. chmod u=rw,g=rw,o=rw $OUT
  38.  
  39. echo x - Makefile
  40. if test -f Makefile ; then
  41.     echo Makefile exists, putting output in $$Makefile
  42.     OUT=$$Makefile
  43.     STATUS=1
  44. else
  45.     OUT=Makefile
  46. fi
  47. sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
  48. XXall:    targ tarl
  49.  
  50. XXtarg:    targ.c
  51. XX    cc $(CFLAGS) -o $@ $<
  52.  
  53. XXtarl:    tarl.c
  54. XX    cc $(CFLAGS) -o $@ $<
  55.  
  56. XX# The 'echo' causes the "right thing" to happen on 4.[23]BSD systems.
  57. XXDEST    = /usr/local/bin
  58. XXMAN    = /usr/man/man1
  59. XXinstall:    all
  60. XX    cp targ tarl $DEST
  61. XX    cp targ.1 $MAN/targ.1
  62. XX    echo ".so man1/tarl.1" >$MAN/targ.1
  63. @//E*O*F Makefile//
  64. chmod u=rw,g=rw,o=rw $OUT
  65.  
  66. echo x - targ.1
  67. if test -f targ.1 ; then
  68.     echo targ.1 exists, putting output in $$targ.1
  69.     OUT=$$targ.1
  70.     STATUS=1
  71. else
  72.     OUT=targ.1
  73. fi
  74. sed 's/^XX//' > $OUT <<'@//E*O*F targ.1//'
  75. XX.TH TARG 1 local
  76. XX.DA 23 July 1986
  77. XX.SH NAME
  78. XXtarg, tarl \- recover files from damaged tar-format archives
  79. XX.SH SYNOPSIS
  80. XX\fBtarg\fR file ...
  81. XX.PP
  82. XX\fBtarl\fR
  83. XX.SH DESCRIPTION
  84. XX\fITarg\fR and \fItarl\fR are used to list and recover files from a
  85. XXdamaged \fItar\fR(1) archive.
  86. XXThey use a simplistic pattern-matching
  87. XXapproach to identify \fItar\fR header blocks.
  88. XXBoth will cheerfully ignore all sorts of bad things about the archive
  89. XX(such as wrong checksums, read errors, and scraped-off magnetic surface...),
  90. XXup to a maximum of twenty hard errors in a row.
  91. XXThey report on such things as apparent end-of-file.
  92. XXBoth programs read the \fItar\fR archive from standard input.
  93. XX.PP
  94. XX\fITarl\fR lists the file names it sees in the archive.
  95. XXIt is particularly useful for 
  96. XXpreparing a file of names for use with \fItarg\fR.
  97. XX.PP
  98. XX\fITarg\fR takes file or directory names as arguments
  99. XXand attempts to extract them from the archive.
  100. XX\fITarg\fR is not willing to create directories, however,
  101. XXso these must be made manually beforehand if they do not already exist.
  102. XXFiles are owned by the user, and have his default permissions.
  103. XX.SH EXAMPLE
  104. XX``tarl < /dev/rmt8 > filelist'' lists all files on the tape
  105. XXmounted on /dev/rmt8 and places the results in ``filelist''.
  106. XX.PP
  107. XX``targ joe/precious < /dev/rmt0'' restores the file
  108. XX``joe/precious'' from the tape mounted on /dev/rmt0.
  109. XXThe directory ``joe'' must already exist.
  110. XX.SH SEE ALSO
  111. XXtar(1)
  112. XX.SH HISTORY
  113. XXWritten by Henry Spencer, Univ. of Toronto Zoology.
  114. XXThis software is public domain.
  115. XXManual page by Chris Robertson.
  116. XX.SH BUGS
  117. XX\fITarg\fR should be smarter about directories and permissions.
  118. XX.PP
  119. XXThey really should use the \fItar\fR header-block checksum,
  120. XXinstead of the slightly-arcane pattern matcher, to identify header blocks.
  121. @//E*O*F targ.1//
  122. chmod u=rw,g=rw,o=rw $OUT
  123.  
  124. echo x - targ.c
  125. if test -f targ.c ; then
  126.     echo targ.c exists, putting output in $$targ.c
  127.     OUT=$$targ.c
  128.     STATUS=1
  129. else
  130.     OUT=targ.c
  131. fi
  132. sed 's/^XX//' > $OUT <<'@//E*O*F targ.c//'
  133. XX#include <stdio.h>
  134.  
  135. XX#define NAMSIZ 100
  136. XXstruct matches {
  137. XX    int offset;
  138. XX    char value;
  139. XX} matches[] = {
  140. XX    NAMSIZ+6,    ' ',
  141. XX    NAMSIZ+7,    '\0',
  142. XX    NAMSIZ+8+6,    ' ',
  143. XX    NAMSIZ+8+7,    '\0',
  144. XX    NAMSIZ+16+6,    ' ',
  145. XX    NAMSIZ+16+7,    '\0',
  146. XX    NAMSIZ+24+11,    ' ',
  147. XX    NAMSIZ+36+11,    ' ',
  148. XX    NAMSIZ+48+6,    '\0',
  149. XX    0,        0,
  150. XX};
  151.  
  152. XXint
  153. XXistar(block)
  154. XXchar *block;
  155. XX{
  156. XX    int loop;
  157.  
  158. XX    for (loop = 0; matches[loop].offset != 0; loop++)
  159. XX        if (block[matches[loop].offset] != matches[loop].value)
  160. XX            return(0);
  161. XX    return(1);
  162. XX}
  163.  
  164. XXchar buf[10240];
  165. XXint bad;
  166. XXint nleft = 0;
  167. XXint whichnow;
  168.  
  169. XXint opened = 0;
  170. XXint f;
  171. XXlong nwrite;
  172.  
  173. XXmain(argc, argv)
  174. XXint argc;
  175. XXchar **argv;
  176. XX{
  177. XX    int loop;
  178. XX    char *block;
  179. XX    extern char *readblock();
  180.  
  181. XX    bad = 0;
  182.  
  183. XX    for(;;) {
  184. XX        block = readblock(0);
  185.  
  186. XX        if (block != NULL)
  187. XX            doblock(block, argc, argv);
  188. XX    }
  189. XX}
  190.  
  191. XXdoblock(block, argc, argv)
  192. XXchar *block;
  193. XXint argc;
  194. XXchar **argv;
  195. XX{
  196. XX    int count;
  197.  
  198. XX    if (istar(block)) {
  199. XX        if (opened) {
  200. XX            printf("--- premature end\n");
  201. XX            close(f);
  202. XX            opened = 0;
  203. XX        }
  204. XX        if (match(block, argc, argv)) {
  205. XX            f = creat(block, 0666);
  206. XX            if (f < 0)
  207. XX                printf("--- unable to create %s\n", block);
  208. XX            else {
  209. XX                opened = 1;
  210. XX                sscanf(block+NAMSIZ+24, "%lo", &nwrite);
  211. XX                printf("--- reading %s %ld\n", block, nwrite);
  212. XX                if (nwrite <= 0) {
  213. XX                    close(f);
  214. XX                    opened = 0;
  215. XX                    printf("--- done\n");
  216. XX                }
  217. XX            }
  218. XX        }
  219. XX    } else {
  220. XX        if (opened) {
  221. XX            count = (nwrite > 512) ? 512 : (int)nwrite;
  222. XX            write(f, block, count);
  223. XX            nwrite -= count;
  224. XX            if (nwrite <= 0) {
  225. XX                opened = 0;
  226. XX                close(f);
  227. XX                printf("--- done\n");
  228. XX            }
  229. XX        }
  230. XX    }
  231. XX}
  232.  
  233. XXint
  234. XXmatch(s, argc, argv)
  235. XXchar *s;
  236. XXint argc;
  237. XXchar **argv;
  238. XX{
  239. XX    int i;
  240. XX    int c;
  241.  
  242. XX    for (i = 1; i < argc; i++) {
  243. XX        if (strncmp(s, argv[i], strlen(argv[i])) == 0) {
  244. XX            c = s[strlen(argv[i])];
  245. XX            if (c == '\0' || c == '/')
  246. XX                return(1);
  247. XX        }
  248. XX    }
  249. XX    return(0);
  250. XX}
  251.  
  252. XXchar *
  253. XXreadblock(desc)
  254. XXint desc;
  255. XX{
  256. XX    int count;
  257.  
  258. XX    if (nleft > 0) {
  259. XX        whichnow++;
  260. XX        nleft--;
  261. XX        return(buf+whichnow*512);
  262. XX    }
  263.  
  264. XX    count = read(desc, buf, (int)sizeof(buf));
  265. XX    if (count <= 0 || count%512 != 0) {
  266. XX        if (count == 0)
  267. XX            printf("---apparent EOF\n");
  268. XX        else
  269. XX            printf("---error\n");
  270. XX        if (bad > 20)
  271. XX            exit(1);
  272. XX        bad++;
  273. XX        return(NULL);
  274. XX    }
  275. XX    bad = 0;
  276. XX    whichnow = 0;
  277. XX    nleft = count/512 - 1;
  278. XX    return(buf);
  279. XX}
  280. @//E*O*F targ.c//
  281. chmod u=rw,g=rw,o=rw $OUT
  282.  
  283. echo x - tarl.c
  284. if test -f tarl.c ; then
  285.     echo tarl.c exists, putting output in $$tarl.c
  286.     OUT=$$tarl.c
  287.     STATUS=1
  288. else
  289.     OUT=tarl.c
  290. fi
  291. sed 's/^XX//' > $OUT <<'@//E*O*F tarl.c//'
  292. XX#include <stdio.h>
  293.  
  294. XX#define NAMSIZ 100
  295. XXstruct matches {
  296. XX    int offset;
  297. XX    char value;
  298. XX} matches[] = {
  299. XX    NAMSIZ+6,    ' ',
  300. XX    NAMSIZ+7,    '\0',
  301. XX    NAMSIZ+8+6,    ' ',
  302. XX    NAMSIZ+8+7,    '\0',
  303. XX    NAMSIZ+16+6,    ' ',
  304. XX    NAMSIZ+16+7,    '\0',
  305. XX    NAMSIZ+24+11,    ' ',
  306. XX    NAMSIZ+36+11,    ' ',
  307. XX    NAMSIZ+48+6,    '\0',
  308. XX    0,        0,
  309. XX};
  310.  
  311. XXint
  312. XXistar(block)
  313. XXchar *block;
  314. XX{
  315. XX    int loop;
  316.  
  317. XX    for (loop = 0; matches[loop].offset != 0; loop++)
  318. XX        if (block[matches[loop].offset] != matches[loop].value)
  319. XX            return(0);
  320. XX    return(1);
  321. XX}
  322.  
  323. XXchar buf[10240];
  324. XXint bad;
  325. XXint nleft = 0;
  326. XXint whichnow;
  327.  
  328. XXmain()
  329. XX{
  330. XX    int loop;
  331. XX    int dir;
  332. XX    char *block;
  333. XX    extern char *readblock();
  334.  
  335. XX    bad = 0;
  336.  
  337. XX    for(;;) {
  338. XX        block = readblock(0);
  339.  
  340. XX        if (block != NULL && istar(block))
  341. XX            printf("%s\n", block);
  342. XX    }
  343. XX}
  344.  
  345. XXchar *
  346. XXreadblock(desc)
  347. XXint desc;
  348. XX{
  349. XX    int count;
  350.  
  351. XX    if (nleft > 0) {
  352. XX        whichnow++;
  353. XX        nleft--;
  354. XX        return(buf+whichnow*512);
  355. XX    }
  356.  
  357. XX    count = read(desc, buf, (int)sizeof(buf));
  358. XX    if (count <= 0 || count%512 != 0) {
  359. XX        if (count == 0)
  360. XX            printf("---apparent EOF\n");
  361. XX        else
  362. XX            printf("---error\n");
  363. XX        if (bad > 20)
  364. XX            exit(1);
  365. XX        bad++;
  366. XX        return(NULL);
  367. XX    }
  368. XX    bad = 0;
  369. XX    whichnow = 0;
  370. XX    nleft = count/512 - 1;
  371. XX    return(buf);
  372. XX}
  373. @//E*O*F tarl.c//
  374. chmod u=rw,g=rw,o=rw $OUT
  375.  
  376. echo Inspecting for damage in transit...
  377. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  378. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  379. cat > $temp <<\!!!
  380.        6      60     398 README
  381.       15      48     295 Makefile
  382.       46     274    1744 targ.1
  383.      147     329    2148 targ.c
  384.       81     163    1112 tarl.c
  385.      295     874    5697 total
  386. !!!
  387. wc $FILES | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  388. if test -s $dtemp ; then
  389.     echo "Ouch [diff of wc output]:"
  390.     cat $dtemp
  391.     STATUS=1
  392. elif test $STATUS = 0 ; then
  393.     echo "No problems found."
  394. else
  395.     echo "WARNING -- PROBLEMS WERE FOUND..."
  396. fi
  397. exit $STATUS
  398.